using logging;
using System.Collections;


// 享元模式最核心的意图：减少巨大开销对象的创建
public class Website{
    protected string _type;
    public Website(string type){
        this._type = type;
        alloc_vpc();  // 开销巨大
    }

    protected void alloc_vpc(){  // VPC: VirtualPrivateServer
        Log.print($"【{_type}类】网站: 租用新的虚拟主机空间, 花销￥300");
    }

    // 不同的 Website，也有着不同的表现层
    public void decorate_space(IUser user, int money_for_ui){
        user.reset_web_ui(money_for_ui);  // 实际上，享元对象将外部状态分离为user对象，由user对象处理变化部分
                                          // 由于user对象的创建开销很小，故而减少了整体项目的开销。
    }
}

public interface IUser{  // 针对接口编程
    void reset_web_ui(int money);
}

public class User: IUser{
    public string user{get;}
    public User(string user){ this.user = user; }

    public void reset_web_ui(int money){
        Log.print($"{user}: 配置个人网站-私人空间，花销￥{money}");
    }
}

class WebSiteFactory{  // 通过工厂类，实现对“共享内存”的复用
    private Hashtable flyweights = new Hashtable();
    public Website build_website(string key){
        if(!flyweights.ContainsKey(key)){
            flyweights.Add(key, new Website(key));  // 通过hash等方式，减少大对象的创建
        }
        return (Website)flyweights[key];
    }
}

class Demo{
    static void Main(){
        var factory = new WebSiteFactory();
        var wang = new User("隔壁老王");

        var blog_website = factory.build_website("博客");
        blog_website.decorate_space(new User("Myself"), 10);

        var blog_2 = factory.build_website("博客");
        blog_2.decorate_space(wang, 50);

        var forum = factory.build_website("论坛");
        forum.decorate_space(new User("天涯"), 99);
    
        var movie = factory.build_website("视频");
        movie.decorate_space(wang, 20);

        var movie_2 = factory.build_website("视频");
        movie_2.decorate_space(new User("NoName"), 10);
    }
}

/* 客户端中，我们可以任性的创建各种享元对象和User对象，
   但实际上，真正的“庞大”对象没有几个，这些大对象保留了项目的不变部分。
   而User小对象的创建开销是可以忽略的，而他们实现了项目的变化部分。
 */